﻿using System;
using System.Xml;

namespace IniFileManager
{
	/// <summary>
	/// Class representing inner structure of an float element
	/// within property defined by library user in ini schema.
	/// </summary>
	internal sealed class IniFloatElementSchema : IniElementSchema
	{
		private readonly float defaultValue;
		private readonly float minValue;
		private readonly float maxValue;

		/// <summary>
		/// Creates "IniFloatElementSchema" from xml node in ini schema xml representation.
		/// </summary>
		/// <param name="floatElementNode">Ini float element schema xml node.</param>
		/// <exception cref="System.FormatException">Trown if is provided xml node not valid float element node.</exception>
		internal IniFloatElementSchema( XmlNode floatElementNode )
		{
			// Embedded "IniSchema.xsd"'s definition guarantees existence and format of this attribute:
			this.defaultValue = float.Parse( floatElementNode.Attributes[IniSchemaXsd.ATTRIBUTE_DEFAULT].Value, IniSchemaXsd.cultureInfo );
			if( floatElementNode.Attributes[IniSchemaXsd.ATTRIBUTE_MIN] != null )
			{
				this.minValue = float.Parse( floatElementNode.Attributes[IniSchemaXsd.ATTRIBUTE_MIN].Value, IniSchemaXsd.cultureInfo );
			}
			else
			{
				this.minValue = float.MinValue;
			}
			if( floatElementNode.Attributes[IniSchemaXsd.ATTRIBUTE_MAX] != null )
			{
				this.maxValue = float.Parse( floatElementNode.Attributes[IniSchemaXsd.ATTRIBUTE_MAX].Value, IniSchemaXsd.cultureInfo );
			}
			else
			{
				this.maxValue = float.MaxValue;
			}

			// If condition minValue <= defaultValue <= maxValue isn't satisfied, 
			// throw an exception. (Rewritten using deMorgan rules):
			if( defaultValue < minValue || defaultValue > maxValue )
			{
				throw new ArgumentException();
			}
		}

		/// <summary>
		/// Boxed default float value of an element into object.
		/// </summary>
		internal override object DefaulValue
		{
			get
			{
				return this.defaultValue;
			}
		}

		/// <summary>
		/// Tells wheather a value is valid within.
		/// </summary>
		/// <param name="boxedValue">Value boxed in object.</param>
		/// <returns>True if value valid within. False if not.</returns>
		internal override bool IsValueValidWithin( object boxedValue )
		{
			float value;
			try
			{
				value = (float)boxedValue;
			}
			catch
			{
				return false;
			}

			// If condition minValue <= defaultValue <= maxValue isn't satisfied, 
			// value is not valid within.
			if( value >= this.minValue && value <= this.maxValue )
			{
				return true;
			}
			else
			{
				return false;
			}
		}

	}
}
